// ****************************************************************
// Copyright 2012, Stephan Burguchev
// e-mail: me@sburg.net
// ****************************************************************
// *
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using Updater.Common;

namespace Updater.Utils
{
    public static class NamedPipeHelper
    {
        public static void ReadData(string pipeName, Stream outStream)
        {
            if (pipeName == null)
            {
                throw new ArgumentNullException("pipeName");
            }

            if (outStream == null)
            {
                throw new ArgumentNullException("outStream");
            }

            using (var pipeClient = new NamedPipeClientStream(".", pipeName, PipeDirection.In))
            {
                pipeClient.Connect();

                pipeClient.CopyTo(outStream);
            }
        }

        public static Process StartProcessAndWriteData(ProcessStartInfo startInfo, Stream data)
        {
            if (startInfo == null)
            {
                throw new ArgumentNullException("startInfo");
            }

            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            try
            {
                var childProcess = new Process
                    {
                        StartInfo = startInfo
                    };

                string pipeName = Guid.NewGuid().ToString();
                using (var pipeServer = new NamedPipeServerStream(pipeName, PipeDirection.Out, 1, PipeTransmissionMode.Message))
                {
                    // Pass the client process a name of the pipe.
                    childProcess.StartInfo.Arguments = pipeName;

                    try
                    {
                        childProcess.Start();
                    }
                    catch (Win32Exception ex)
                    {
                        if (ex.NativeErrorCode == 1223)
                        {
                            // The user denied UAC escalation
                            return null;
                        }

                        throw;
                    }

                    pipeServer.WaitForConnection();

                    data.CopyTo(pipeServer);
                }

                return childProcess;
            }
            catch (Exception ex)
            {
                throw new UpdaterException("Failed to start a child process or open an anonymous pipe to it.", ex);
            }
        }
    }
}
